<template>
  <div>
    <canvas
      ref="captcha"
      :height="captchaConfig.height"
      :width="captchaConfig.width"
      @click="draw"
    ></canvas>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'

const captchaResult = ref<string>('')

const captcha = ref<any>(null)
const captchaConfig = reactive({
  pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789',
  width: 110,
  height: 30,
  removeChars: 'iI10Oo',
  dotsNumber: 20,
  lineNumber: 2
})
const randomNum = (min: any, max: any) => {
  return parseInt(Math.random() * (max - min) + min)
}

const randomColor = (min: any, max: any) => {
  const r = randomNum(min, max)
  const g = randomNum(min, max)
  const b = randomNum(min, max)
  return `rgb(${r},${g},${b})`
}

const drawLines = () => {
  const ctx = captcha.value.getContext('2d')
  for (let i = 0; i < captchaConfig.lineNumber; i++) {
    ctx.strokeStyle = randomColor(100, 200)
    ctx.beginPath()
    ctx.moveTo(0, randomNum(10, captchaConfig.height - 10))
    ctx.bezierCurveTo(
      captchaConfig.width / 3,
      randomNum(10, captchaConfig.height - 10),
      (2 * captchaConfig.width) / 3,
      randomNum(10, captchaConfig.height - 10),
      captchaConfig.width,
      randomNum(10, captchaConfig.height - 10)
    )
    ctx.stroke()
  }
}

const drawDots = () => {
  const ctx = captcha.value.getContext('2d')
  for (let i = 0; i < captchaConfig.dotsNumber; i++) {
    ctx.fillStyle = randomColor(100, 200)
    ctx.beginPath()
    ctx.arc(
      randomNum(0, captchaConfig.width),
      randomNum(0, captchaConfig.height),
      2,
      0,
      Math.PI * 2
    )
    ctx.fill()
  }
}

const draw = () => {
  const arr = []
  const ctx = captcha.value.getContext('2d')
  ctx.fillStyle = randomColor(180, 230)
  ctx.fillRect(0, 0, captchaConfig.width, captchaConfig.height)

  drawLines()
  drawDots()

  const filteredPool = captchaConfig.pool
    .split('')
    .filter((char) => !captchaConfig.removeChars.includes(char))
    .join('')
  for (let i = 0; i < 4; i++) {
    const text = filteredPool[randomNum(0, filteredPool.length)]
    const fontSize = randomNum(18, 28)
    const deg = randomNum(-20, 20)

    const x = (captchaConfig.width / 4) * i + captchaConfig.width / 8
    const y = captchaConfig.height / 2

    ctx.font = fontSize + 'px Algerian'
    ctx.textBaseline = 'middle'
    ctx.textAlign = 'center'
    ctx.fillStyle = randomColor(0, 100)
    ctx.save()
    ctx.translate(x, y)
    ctx.rotate((deg * Math.PI) / 180)
    ctx.fillText(text, 0, 0)
    ctx.restore()
    arr.push(text)
  }

  captchaResult.value = arr.join('')
  getCaptchaValue()
}

const emit = defineEmits(['getCaptchaValue'])
const getCaptchaValue = () => {
  emit('getCaptchaValue', captchaResult.value)
}

defineExpose({
  draw
})

onMounted(() => {
  draw()
})
</script>

<style scoped lang="sass">
div
  display: flex
</style>
